package com.adu.music.parser;

import com.adu.music.bean.ArtistCategory;
import com.adu.music.util.CommonUtils;
import com.adu.music.util.DbUtils;
import com.adu.music.util.JsoupUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author duchuanchuan
 * @date 2016/12/12
 */
public class ArtistParser {
    private static final Logger logger = LoggerFactory.getLogger(ArtistParser.class);

    /**
     * 从歌手页面分析出歌手列表
     * http://music.163.com/discover/artist/cat?id=1001&initial=65
     * @param cate 歌手种类
     * @return 歌手集合
     */
    public static List<Map<String, Object>> parseArtistList(ArtistCategory cate) {
        String url = "http://music.163.com/discover/artist/cat?id=" + cate.getId() + "&initial=" + cate.getInitial();
        int cateId = cate.getId();
        List<Map<String, Object>> maps = new ArrayList<>();
        Optional<Document> docOptional = JsoupUtils.get(url);
        docOptional.ifPresent(doc -> {
            Elements spans = doc.select("h3 span");
            if (spans.size() > 0) {
                String categoryName = spans.get(0).text();
                Elements elements = doc.select("#m-artist-box li");
                for (Element e : elements) {
                    Element a = e.select(".nm").get(0);
                    String artistId = StringUtils.substringAfter(a.attr("href"), "=");
                    String artistName = a.text();
                    if (StringUtils.isNotBlank(artistName) &&
                            StringUtils.isNotBlank(categoryName) &&
                            StringUtils.isNotBlank(artistId)) {
                        if (isArtistCrawled(artistId)) {
                            logger.info("歌手:{}已经存在", artistId);
                            continue;
                        }
                        Map<String, Object> map = new HashMap<>();
                        map.put("id", CommonUtils.parseInt(artistId));
                        map.put("name", artistName);
                        map.put("category_id", cateId);
                        map.put("category_name", categoryName);
                        logger.info("id : {},name: {},category_id: {},category_name: {}", artistId, artistName, cateId, categoryName);
                        maps.add(map);
                    }
                }
            }
        });
        return maps;
    }

    private static boolean isArtistCrawled(String artistId) {
        List<Map<String, Object>> list = DbUtils.getJdbcTemplate().queryForList("select id from artist where id=" + artistId);
        return list.size() == 1;
    }

    /**
     * 根据歌手ID获取top50歌曲id集合
     * @param artistId 歌手ID
     * @return 歌曲集合
     */
    public static List<String> parseTo50SongIds(String artistId) {
        String url = "http://music.163.com/artist?id=" + artistId;
        final List<String> songIds = new ArrayList<>();
        Optional<Document> docOptional = JsoupUtils.get(url);
        docOptional.ifPresent(doc -> {
            Optional<Element> songlistDiv = Optional.ofNullable(doc.getElementById("song-list-pre-cache"));
            songlistDiv.ifPresent(sldiv -> {
                Elements songAnchors = sldiv.select("li a");
                songAnchors.forEach(a -> {
                    String id = StringUtils.substringAfter(a.attr("href"), "id=");
                    if (StringUtils.isNotBlank(id)) songIds.add(id);
                });
            });
        });
        return songIds;
    }


    /**
     * 抓取该歌手top50歌曲中的mv
     * @param artistId 歌手Id
     * @return MV集合
     */
    public static List<Map<String, Object>> parseTop50Mvs(String artistId) {
        String url = "http://music.163.com/artist?id=" + artistId;
        final List<Map<String, Object>> mvs = new ArrayList<>();
        Optional<Document> docOptional = JsoupUtils.get(url);
        docOptional.ifPresent(doc -> {
            if(StringUtils.contains(doc.html(), "网页找不到")){
                logger.info("你要查找的网页找不到,url:{}", url);
                return;
            }
            Element artistNameNode = doc.getElementById("artist-name");
            if (artistNameNode == null) {
                logger.info("抓取MV: {} 异常,貌似没找到artist_name", artistId);
                return;
            }
            String artistName = artistNameNode.attr("title");
            Optional<Element> songListDiv = Optional.ofNullable(doc.getElementById("song-list-pre-cache"));
            songListDiv.ifPresent((Element songDiv) -> {
                Elements textAreas = songDiv.getElementsByTag("textarea");
                if (textAreas.size() == 0) return;
                String songsText = textAreas.get(0).text();
                if (StringUtils.isNotBlank(songsText)) {
                    JSONArray songArray = JSONArray.parseArray(songsText);
                    songArray.forEach(song -> {
                        JSONObject songObj = (JSONObject) song;
                        Map<String, Object> mv = new HashMap<>();
                        String mvId = songObj.getString("mvid");
                        if (StringUtils.equals(mvId, "0")) {
                            return;
                        }
                        String mvName = songObj.getString("name");
                        mv.put("id", mvId);
                        mv.put("name", mvName); // 就是歌曲的名字
                        mv.put("artist_id", CommonUtils.parseInt(artistId));
                        mv.put("artist_name", artistName);
                        mv.put("song_id", songObj.getIntValue("id"));
                        int comment = MvParser.parseComment(mvId);
                        mv.put("comment", comment);
                        logger.info("抓取MV,ID:{},name:{},artist_name:{},comment:{}", mvId, mvName, artistName, comment);
                        // Map<String, String> mapDetail = MvParser.parseVideo(String.valueOf(mvId));
                        mvs.add(mv);
                    });
                }
            });
        });
        return mvs;
    }

}
